using CfgTable;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;
using NetProtocol.Enum;
using NetProtocol.POD;
using System.Collections.Generic;

namespace IQIGame.Onigao.Logic
{
    public class ExecBattle : BaseServiceExecution
    {
        public override void Execute(LevelRegion region, LevelPlayer player)
        {
            if (player == null)
            {
                LogicLog.LogError($"服务{serviceCid}中的战斗执行失败，玩家为空。");
                return;
            }
            if (player.entity.isOccupied)
            {
                LogicLog.LogError($"服务{serviceCid}中的战斗执行运行失败，玩家已处于占用状态：{player.entity.DebugOccupationLog()}。");
                return;
            }
            if (triggerEntity != null && triggerEntity.isOccupied)
            {
                LogicLog.LogError($"服务{serviceCid}中的战斗执行运行失败，实体[mcid: {triggerEntity.entityConfig.id}]已处于占用状态：{player.entity.DebugOccupationLog()}。");
                return;
            }
            var config = _config as ExecParamBattle;
            if (!config.monsterTeam.TryGetValue(triggerEntity, out var monsterTeamGroupCid))
            {
                LogicLog.LogError($"开始战斗错误，找不到monster team group的cid。triggering entity id: {triggerEntity?.id}");
                return;
            }

            //占用
            triggerEntity?.OccupiedBy(EntityOccupationStatus.Battle, 0, player.entity);
            player.entity.OccupiedBy(EntityOccupationStatus.Battle, monsterTeamGroupCid, triggerEntity);

            var cfgMonsterTeamGroup = TableCenter.monsterTeamGroup.Get(monsterTeamGroupCid);

            var rBattleSceneConfig = TableCenter.battleScene.Get(cfgMonsterTeamGroup.BattleScene);
            CreateBattlePOD battlePOD = new CreateBattlePOD()
            {
                id = LogicHelper.AllocGUID(),
                battleType = BattleType.Level,
                randomSeed = region.level.random.randomInt(int.MaxValue),
                battleScene = rBattleSceneConfig.Id,
                hostPlayerId = player.id,
                isLocal = region.level.isLocal,
                strikeTeam = (BattleTeamId)config.strikeTeam,
                unsafe_redTeams = CreatePlayerTeam(player),
                unsafe_blueTeams = CreateMonsterTeam(cfgMonsterTeamGroup.MonsterTeamID, rBattleSceneConfig),
                unsafe_allPlayers = new List<long> { player.id },
            };
            LogicPlayerPOD logicPlayerPOD = new LogicPlayerPOD();
            logicPlayerPOD.pid = player.id;
            logicPlayerPOD.name = player.logicPlayer.name;

            var tempParamList = ListPool<int>.Get();
            {
                tempParamList.Add(monsterTeamGroupCid);
                LogicQuestModule.Instance.CheckTarget(player.logicPlayer, QuestTargetType.FightWithMonster, tempParamList);
            }
            ListPool<int>.Put(tempParamList);

            SLevelLogicModule.Instance.StartBattle(player, battlePOD, logicPlayerPOD);
        }

        private List<BattleTeamPOD> CreatePlayerTeam(LevelPlayer player)
        {
            var rList = new List<BattleUnitPOD>();
            var rPOD = new BattleTeamPOD()
            {
                teamIndex = BattleConst.TeamRedIndex,
                unsafe_units = rList,
            };
            foreach (var kv in player.logicPlayer.formation.heroes)
            {
                if (!kv.Value.HasHero) continue;

                int formationIndex = kv.Key - 1;
                var heroData = kv.Value.heroData;
                var rUnitPOD = UnitFactory.CreateHeroPOD(heroData.cid, heroData.skinCid, heroData.attrs, heroData.allSkills, heroData.level);
                rUnitPOD.pid = player.id;
                rUnitPOD.formationIndex = formationIndex;
                if (!kv.Value.isBench)
                {
                    rList.Add(rUnitPOD);
                }
                else
                {
                    rPOD.substitute = rUnitPOD;
                }
            }
            return new() { rPOD };
        }

        private List<BattleTeamPOD> CreateMonsterTeam(IReadOnlyList<int> rMonsterTeam, CfgBattleScene rSceneConfig)
        {
            var rListTeam = new List<BattleTeamPOD>();
            for (int i = 0; i < rMonsterTeam.Count; i++)
            {
                rListTeam.Add(UnitFactory.CreateMonsterTeamPOD(rMonsterTeam[i]));
            }
            return rListTeam;
        }
    }
}